package com.techzhi.tidb.service;

import com.techzhi.tidb.loader.TiDBUtilsLoader;
import com.techzhi.tidb.model.TableColumnInfo;
import com.techzhi.tidb.pool.TiDBConnectionPoolManager;
import com.techzhi.tidb.utils.TiDBOperationUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TiDB统一服务接口
 * 为业务代码提供统一的TiDB操作入口
 *
 * @author shouzhi
 * @date 2025-09-01
 */

@Slf4j
public class TiDBService {

    @Autowired
    private TiDBOperationUtils operationUtils;

    @Autowired
    private TiDBConnectionPoolManager connectionPoolManager;

    @Autowired
    private TiDBUtilsLoader utilsLoader;

    /**
     * 确保TiDB已初始化
     */
    private void ensureInitialized() {
        if (!utilsLoader.isLoaded()) {
            log.info("TiDB未初始化，开始动态加载...");
            utilsLoader.loadTiDBUtils();
        }
    }

    /**
     * 查询数据
     */
    public List<Map<String, Object>> query(String sql, Object... params) {
        ensureInitialized();
        return operationUtils.executeQuery(sql, params);
    }

    /**
     * 查询数据（带超时）
     */
    public List<Map<String, Object>> query(String sql, int timeoutSeconds, Object... params) {
        ensureInitialized();
        return operationUtils.executeQuery(sql, timeoutSeconds, params);
    }

    /**
     * 更新数据
     */
    public int update(String sql, Object... params) {
        ensureInitialized();
        return operationUtils.executeUpdate(sql, params);
    }

    /**
     * 更新数据（带超时）
     */
    public int update(String sql, int timeoutSeconds, Object... params) {
        ensureInitialized();
        return operationUtils.executeUpdate(sql, timeoutSeconds, params);
    }

    /**
     * 批量操作
     */
    public int[] batchUpdate(String sql, List<Object[]> paramsList) {
        ensureInitialized();
        return operationUtils.executeBatch(sql, paramsList);
    }

    /**
     * 批量操作（带批量大小和超时控制）
     */
    public int[] batchUpdate(String sql, List<Object[]> paramsList, int batchSize, int timeoutSeconds) {
        ensureInitialized();
        return operationUtils.executeBatch(sql, paramsList, batchSize, timeoutSeconds);
    }

    /**
     * 事务操作
     */
    public <T> T executeInTransaction(TiDBOperationUtils.TransactionCallback<T> callback) {
        ensureInitialized();
        return operationUtils.executeInTransaction(callback);
    }

    /**
     * 事务操作（指定隔离级别）
     */
    public <T> T executeInTransaction(TiDBOperationUtils.TransactionCallback<T> callback, int isolationLevel) {
        ensureInitialized();
        return operationUtils.executeInTransaction(callback, isolationLevel);
    }

    /**
     * 获取表结构
     */
    public List<TableColumnInfo> getTableStructure(String tableName) {
        ensureInitialized();
        return operationUtils.getTableStructure(tableName);
    }

    /**
     * 获取所有表名
     */
    public List<String> getAllTableNames() {
        ensureInitialized();
        return operationUtils.getAllTableNames();
    }

    /**
     * 获取表行数
     */
    public long getTableRowCount(String tableName) {
        ensureInitialized();
        return operationUtils.getTableRowCount(tableName);
    }

    /**
     * 检查表是否存在
     */
    public boolean tableExists(String tableName) {
        ensureInitialized();
        return operationUtils.tableExists(tableName);
    }

    /**
     * 获取数据库版本
     */
    public String getDatabaseVersion() {
        ensureInitialized();
        return operationUtils.getDatabaseVersion();
    }

    /**
     * 连接池状态
     */
    public Map<String, Object> getConnectionPoolStats() {
        if (!utilsLoader.isLoaded()) {
            Map<String, Object> errorMap = new HashMap<>();
            errorMap.put("error", "TiDB未初始化");
            return errorMap;
        }
        return connectionPoolManager.getPoolStats();
    }

    /**
     * 健康检查
     */
    public boolean healthCheck() {
        try {
            if (!utilsLoader.isLoaded()) {
                log.debug("TiDB未加载，健康检查失败");
                return false;
            }

            return operationUtils.testConnection();
        } catch (Exception e) {
            log.error("TiDB健康检查失败", e);
            return false;
        }
    }

    /**
     * 详细健康检查
     */
    public HealthCheckResult detailedHealthCheck() {
        HealthCheckResult result = new HealthCheckResult();

        try {
            // 检查加载状态
            TiDBUtilsLoader.LoadStatus loadStatus = utilsLoader.getLoadStatus();
            result.setLoaded(loadStatus.isLoaded());
            result.setEnabled(loadStatus.isEnabled());
            result.setConfigValid(loadStatus.isConfigValid());
            result.setPoolInitialized(loadStatus.isPoolInitialized());
            result.setPoolHealthy(loadStatus.isPoolHealthy());

            if (loadStatus.isLoaded()) {
                // 检查连接
                result.setConnectionOk(operationUtils.testConnection());

                // 获取版本信息
                if (result.isConnectionOk()) {
                    result.setDatabaseVersion(operationUtils.getDatabaseVersion());
                }

                // 获取连接池信息
                Map<String, Object> poolStats = connectionPoolManager.getPoolStats();
                result.setActiveConnections((Integer) poolStats.getOrDefault("activeConnections", 0));
                result.setTotalConnections((Integer) poolStats.getOrDefault("totalConnections", 0));
                result.setIdleConnections((Integer) poolStats.getOrDefault("idleConnections", 0));
            }

            result.setOverallHealthy(
                result.isEnabled() &&
                result.isLoaded() &&
                result.isConfigValid() &&
                result.isPoolHealthy() &&
                result.isConnectionOk()
            );

        } catch (Exception e) {
            log.error("详细健康检查失败", e);
            result.setOverallHealthy(false);
            result.setErrorMessage(e.getMessage());
        }

        return result;
    }

    /**
     * 重新初始化TiDB
     */
    public void reinitialize() {
        log.info("重新初始化TiDB服务...");
        utilsLoader.reload();
        log.info("TiDB服务重新初始化完成");
    }

    /**
     * 获取TiDB服务状态
     */
    public ServiceStatus getServiceStatus() {
        ServiceStatus status = new ServiceStatus();
        TiDBUtilsLoader.LoadStatus loadStatus = utilsLoader.getLoadStatus();

        status.setEnabled(loadStatus.isEnabled());
        status.setLoaded(loadStatus.isLoaded());
        status.setLoading(loadStatus.isLoading());
        status.setHealthy(healthCheck());

        if (loadStatus.isLoaded()) {
            status.setConnectionInfo(connectionPoolManager.getConfigManager().getMaskedConnectionInfo());
            status.setPoolStats(connectionPoolManager.getPoolStats());
        }

        return status;
    }

    /**
     * 健康检查结果类
     */
    public static class HealthCheckResult {
        private boolean enabled;
        private boolean loaded;
        private boolean configValid;
        private boolean poolInitialized;
        private boolean poolHealthy;
        private boolean connectionOk;
        private boolean overallHealthy;
        private String databaseVersion;
        private int activeConnections;
        private int totalConnections;
        private int idleConnections;
        private String errorMessage;

        // getters and setters
        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }

        public boolean isLoaded() {
            return loaded;
        }

        public void setLoaded(boolean loaded) {
            this.loaded = loaded;
        }

        public boolean isConfigValid() {
            return configValid;
        }

        public void setConfigValid(boolean configValid) {
            this.configValid = configValid;
        }

        public boolean isPoolInitialized() {
            return poolInitialized;
        }

        public void setPoolInitialized(boolean poolInitialized) {
            this.poolInitialized = poolInitialized;
        }

        public boolean isPoolHealthy() {
            return poolHealthy;
        }

        public void setPoolHealthy(boolean poolHealthy) {
            this.poolHealthy = poolHealthy;
        }

        public boolean isConnectionOk() {
            return connectionOk;
        }

        public void setConnectionOk(boolean connectionOk) {
            this.connectionOk = connectionOk;
        }

        public boolean isOverallHealthy() {
            return overallHealthy;
        }

        public void setOverallHealthy(boolean overallHealthy) {
            this.overallHealthy = overallHealthy;
        }

        public String getDatabaseVersion() {
            return databaseVersion;
        }

        public void setDatabaseVersion(String databaseVersion) {
            this.databaseVersion = databaseVersion;
        }

        public int getActiveConnections() {
            return activeConnections;
        }

        public void setActiveConnections(int activeConnections) {
            this.activeConnections = activeConnections;
        }

        public int getTotalConnections() {
            return totalConnections;
        }

        public void setTotalConnections(int totalConnections) {
            this.totalConnections = totalConnections;
        }

        public int getIdleConnections() {
            return idleConnections;
        }

        public void setIdleConnections(int idleConnections) {
            this.idleConnections = idleConnections;
        }

        public String getErrorMessage() {
            return errorMessage;
        }

        public void setErrorMessage(String errorMessage) {
            this.errorMessage = errorMessage;
        }
    }

    /**
     * 服务状态类
     */
    public static class ServiceStatus {
        private boolean enabled;
        private boolean loaded;
        private boolean loading;
        private boolean healthy;
        private String connectionInfo;
        private Map<String, Object> poolStats;

        // getters and setters
        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }

        public boolean isLoaded() {
            return loaded;
        }

        public void setLoaded(boolean loaded) {
            this.loaded = loaded;
        }

        public boolean isLoading() {
            return loading;
        }

        public void setLoading(boolean loading) {
            this.loading = loading;
        }

        public boolean isHealthy() {
            return healthy;
        }

        public void setHealthy(boolean healthy) {
            this.healthy = healthy;
        }

        public String getConnectionInfo() {
            return connectionInfo;
        }

        public void setConnectionInfo(String connectionInfo) {
            this.connectionInfo = connectionInfo;
        }

        public Map<String, Object> getPoolStats() {
            return poolStats;
        }

        public void setPoolStats(Map<String, Object> poolStats) {
            this.poolStats = poolStats;
        }
    }
}
